package com.xbongbong.crm.perform.query.list.business;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.field.VisibleRulePoJo;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.abstracts.AbstractSpecialDataAnalysisHelp;
import com.xbongbong.parent.parse.data.BaseFormDataLinkDataHelp;
import com.xbongbong.parent.parse.data.FormDataLinkDataListServiceImpl;
import com.xbongbong.parent.parse.data.FormDataListAnalysisDataHelp;
import com.xbongbong.parent.parse.data.LinkDataHelp;
import com.xbongbong.pro.customer.pojo.CustomerMainContactPojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.util.SaasLinkProductUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 吴峰
 * @version v1.0
 * @date 2020/4/16 16:32
 * @since v1.0
 */
@Component
public class ContractSpecialDataHandle extends AbstractSpecialDataAnalysisHelp {

    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private ContractModel contractModel;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private BaseFormDataLinkDataHelp baseFormDataLinkDataHelp;
    @Resource
    private LinkDataHelp linkDataHelp;
    @Resource
    private FormDataLinkDataListServiceImpl formDataLinkDataListServiceImpl;

    @Override
    public Integer businessType() {
        return XbbRefTypeEnum.CONTRACT.getCode();
    }

    @Override
    public CustomerMainContactPojo getSpecialData(FormDataListDTO formDataListDTO, PaasFormDataEsListVO formDataEsListVO) throws XbbException {
        boolean productNameNeedHide = false;
        String corpid = formDataListDTO.getCorpid();
        PaasFormExplainEntity productExplain = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        if (Objects.nonNull(productExplain)) {
            Map<String, FieldAttrEntity> productExplainMap = ExplainUtil.getExplainMapByAttr(productExplain.getExplains(), ProductEnum.NAME.getAttr());
            FieldAttrEntity fieldAttrEntity = productExplainMap.get(ProductEnum.NAME.getAttr());
            if (Objects.equals(fieldAttrEntity.getVisibleScopeEnable(), 1)) {
                VisibleRulePoJo visibleScopeRule = fieldAttrEntity.getVisibleScopeRule();
                if (Objects.nonNull(visibleScopeRule)) {
                    fieldAttrEntity.getVisibleScopeRule().setRelative(new ArrayList<>());
                    HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                    BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);
                    productNameNeedHide = ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO);
                }
            }
        }
        List<Long> dataIdIn = new ArrayList<>();
        formDataEsListVO.getPaasFormDataESList().forEach(item->{
            dataIdIn.add(item.getDataId());
        });
        Map<String, FieldAttrEntity> explainMap = formDataEsListVO.getExplainMap() == null ? new HashMap<>(formDataEsListVO.getHeadList().size()) : formDataEsListVO.getExplainMap();
        // 列表页产品子表单回显报错，先取headList用，杰哥说的
        List<FieldAttrEntity> headList = formDataEsListVO.getHeadList();
        if (explainMap.isEmpty()) {
            headList.forEach(item -> explainMap.put(item.getAttr(), item));
        }

        Map<String,Map<Long, List<JSONObject>>> productAttr2Map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String,List<FieldAttrEntity>> keyListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (explainMap.containsKey(ContractEnum.PRODUCT.getAttr())){
            // 获取关联产品的字段
            keyListMap.put(ContractEnum.PRODUCT.getAttr(), SaasLinkProductUtil.listProductLinkKeyField(explainMap.get(ContractEnum.PRODUCT.getAttr())));
            Map<Long, List<JSONObject>> productDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("del",0);
            map.put("contractIdIn", dataIdIn);
            map.put("type",XbbRefTypeEnum.CONTRACT.getCode());
            map.put("orderByStr", "sort asc");
            List<ContractProductEntity> contractProductEntityList = contractProductModel.getSortProducts(map);
            Set<Long> productIdSet = new HashSet<>();
            for (ContractProductEntity entity : contractProductEntityList) {
                Long contractId = entity.getContractId();
                JSONObject productData = contractModel.formatSingleProduct(entity);
                productData.put(StringConstant.DATA_ID,productData.getLong(SelectProductEnum.PRODUCT.getAttr()));
                productData.put(SelectProductEnum.PRODUCT.getAttr(), productNameNeedHide ? null : entity.getProductName());
                List<JSONObject> productDataList = productDataMap.getOrDefault(contractId,new ArrayList<>());
                productDataList.add(productData);
                productDataMap.put(contractId,productDataList);
                productIdSet.add(entity.getProductId());
            }
            productAttr2Map.put(ContractEnum.PRODUCT.getAttr(),productDataMap);
            Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //获取关联字段
            //获取产品数据，最多200条
            if (!productIdSet.isEmpty()){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid))
                        .filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),productIdSet));
                List<PaasFormDataEntityExt> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder, PaasFormDataEntityExt.class,null);
                formDataHelp.setChildSpecification(productList,corpid);
                for (PaasFormDataEntityExt entityExt : productList) {
                    productMap.put(entityExt.getDataId(),entityExt);
                }
            }
            FieldAttrEntity fieldAttrEntity = explainMap.get(ContractEnum.PRODUCT.getAttr());
            List<FieldAttrEntity> linkProductExplainList = (List<FieldAttrEntity>) fieldAttrEntity.getSubForm().getItems();
            // 关联数据
            List<LinkInfoPojo> linkInfoList = new ArrayList<>();
            Map<String, FieldAttrEntity> linkProductExplainMap = new HashMap<>(linkProductExplainList.size());
            Set<String> linkDataAttrSet = new HashSet<>();
            linkProductExplainList.forEach((item) -> {
                if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) && Objects.equals(1, item.getIsRedundant())) {
                    linkInfoList.add(item.getLinkInfo());
                    linkDataAttrSet.add(item.getAttr());
                }
                linkProductExplainMap.put(item.getAttr(), item);
            });
            List<Long> formIdList = new ArrayList<>();
            List<Long> workOrderFormIdList = new ArrayList<>();
            for (LinkInfoPojo linkInfoPojo : linkInfoList) {
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
                } else {
                    formIdList.add(linkInfoPojo.getLinkFormId());
                }
            }
            // 非工单解释
            Map<String, PaasFormExplainEntity> formExplainMap = baseFormDataLinkDataHelp.getExplainMapByFormIdList(formIdList, corpid);
            // 工单解释
            Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = baseFormDataLinkDataHelp.getWorkOrderExplainMapByFormId(workOrderFormIdList, corpid);
            Map<String, Object> linkDataIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Set<Object> linkDataIdSet = new HashSet<>();
            Map<String, Set<String>> subFormLinkDataMap = new HashMap<>();
            contractProductEntityList.forEach(item->{
                FormDataListAnalysisDataHelp.getLinkDataSet(item.getData(), subFormLinkDataMap, linkDataAttrSet, linkDataIdSet, linkDataAttrSet, linkDataIdMap);
            });
            LinkResultDataDTO linkResultDataDTO = new LinkResultDataDTO();
            BeanUtil.copyProperties(formDataListDTO, linkResultDataDTO);
            // 获取关联数据字段所需要的数据
            LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
            linkResultDataVO.setExplainMap(explainMap);
            linkResultDataVO.setLinkDataSet(linkDataIdSet);
            linkResultDataVO.setLinkData(linkDataIdMap);
            linkResultDataVO.setExplainList(linkProductExplainList);
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);

            Map<String, Map<String, FieldAttrEntity>> subExplainMap = new HashMap<>(BasicConstant.ONE);
            Map<Long, List<UnitItemPoJo>> groupItemsMap = relativeProductHelp.getGroupItemsMap(corpid);
            Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = relativeProductHelp.getGroupBaseUnitMap(corpid);
            Iterator<Long> iterator = productDataMap.keySet().iterator();
            while (iterator.hasNext()) {
                Long contractId = iterator.next();
                List<JSONObject> productList = productDataMap.get(contractId);
                if (CollectionsUtil.isNotEmpty(productList)) {
                    for (JSONObject jsonObject : productList) {
                        PaasFormDataEntityExt product = productMap.get(jsonObject.getLong(StringConstant.DATA_ID));
                        if (Objects.nonNull(product)) {
                            for (FieldAttrEntity item : keyListMap.get(ContractEnum.PRODUCT.getAttr())) {
                                if (Objects.equals(item.getFieldType(), FieldTypeEnum.SERIALNO.getType())) {
                                    jsonObject.put(item.getAttr(), product.getSerialNo());
                                } else if (Objects.equals(item.getFieldType(), FieldTypeEnum.ADDTIME.getType())) {
                                    jsonObject.put(item.getAttr(), product.getAddTime());
                                } else if (Objects.equals(item.getFieldType(), FieldTypeEnum.UPDATETIME.getType())) {
                                    jsonObject.put(item.getAttr(), product.getUpdateTime());
                                } else {
                                    jsonObject.put(item.getAttr(), product.getData().get(item.getSaasAttr()));
                                }
                            }
                            // 多单位
                            JSONObject productData = product.getData();
                            //fix bug 34353 (bug原因：产品一开始的单位选择"其他"，输入一个自定义值，eg:"枚"，然后新建一笔合同关联该产品，之后把产品单位设置为多单位，就会导致jsonObject.getLongValue(SelectProductEnum.UNIT.getAttr()) 出错 )
                            Object buinessUnitValObj = jsonObject.get(SelectProductEnum.UNIT.getAttr());
                            if (BasicConstant.ONE.equals(productData.getIntValue(ProductEnum.ENABLE_MULTI_UNIT.getAttr())) && Objects.nonNull(buinessUnitValObj) && (buinessUnitValObj instanceof Number)) {
                                long buinessUnitVal = jsonObject.getLongValue(SelectProductEnum.UNIT.getAttr());
                                long unitGroupId = productData.getLongValue(ProductEnum.UNIT.getAttr());
                                List<UnitItemPoJo> unitItemPoJos = groupItemsMap.get(unitGroupId);
                                jsonObject.put(ProductConstant.TRANSFORM_UNIT_RATE, unitItemPoJos);
                                if (buinessUnitVal < ProductConstant.MAX_SINGLE_UNIT_VALUE) {
                                    MultiUnitItemPoJo multiUnitItemPoJo = groupBaseUnitMap.getOrDefault(unitGroupId, new MultiUnitItemPoJo());
                                    jsonObject.put(SelectProductEnum.UNIT.getAttr(), multiUnitItemPoJo.getBaseValue());
                                }
                            }
                        }
                        for (String item : linkDataAttrSet) {
                            FieldAttrEntity linkDataField = linkProductExplainMap.get(item);
                            boolean isTrue = Objects.isNull(jsonObject.get(item)) || Objects.equals(0L, jsonObject.getLong(item));
                            if (linkDataField == null || isTrue) {
                                continue;
                            }
                            formDataLinkDataListServiceImpl.getLinkDataPrimary(linkResultDataDTO, linkDataField, jsonObject, formDataMap, linkResultDataVO, formExplainMap, workOrderFormExplainMap, subExplainMap);
                        }
                    }
                }
            }
            productAttr2Map.put(ContractEnum.PRODUCT.getAttr(), productDataMap);
        }
        CustomerMainContactPojo customerMainContactPojo = new CustomerMainContactPojo();
        customerMainContactPojo.setProductAttr2Map(productAttr2Map);
        return customerMainContactPojo;
    }

    @Override
    public void setSpecialData(JSONObject resultObject, Long dataId, CustomerMainContactPojo customerMainContactPojo, PaasFormDataEsListVO formDataEsListVO, UserVO loginUser) throws XbbException {

    }
}
